package com.hitqz.robot.biz.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.cache.Cache;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.RateLimiter;
import com.hitqz.robot.api.business.dto.RobotClientSummaryDto;
import com.hitqz.robot.api.business.dto.RobotSendClientMsgDto;
import com.hitqz.robot.api.business.dto.RobotStatusDto;
import com.hitqz.robot.api.business.entity.TicketsEntity;
import com.hitqz.robot.api.business.entity.TicketsTaskEntity;
import com.hitqz.robot.api.business.params.QueryTasksTicketsParams;
import com.hitqz.robot.api.business.vo.TicketsTaskVo;
import com.hitqz.robot.api.business.vo.TicketsVo;
import com.hitqz.robot.api.dispatch.protocol.ProtocolEnum;
import com.hitqz.robot.api.dispatch.protocol.dto.RobotCmdTicketsDto;
import com.hitqz.robot.biz.config.CustomConstant;
import com.hitqz.robot.biz.service.RobotGroupService;
import com.hitqz.robot.biz.service.RobotService;
import com.hitqz.robot.biz.service.TicketsService;
import com.hitqz.robot.biz.service.TicketsTaskService;
import com.hitqz.robot.common.core.util.R;
import com.hitqz.robot.common.security.service.RobotUser;
import com.hitqz.robot.common.security.util.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

/**
 * @author xupkun
 * @date 2024/6/13
 */

@RestController
@AllArgsConstructor
@RequestMapping("/tickets")
@Tag(name = "工单管理")
public class TicketsController {

    private final TicketsService ticketsService;

    private final TicketsTaskService ticketsTaskService;

    private final RobotGroupService robotGroupService;

    private final RobotService robotService;


    @PostMapping("/page")
    @Operation(summary = "分页查询工单列表")
    public R<Page<TicketsVo>> page(@RequestBody QueryTasksTicketsParams queryTicketsParams) {
        LambdaQueryWrapper<TicketsEntity> wrapper = Wrappers.lambdaQuery();
        Page page = new Page(queryTicketsParams.getCurrent(), queryTicketsParams.getSize());
        wrapper.like(StrUtil.isNotBlank(queryTicketsParams.getContent()), TicketsEntity::getName, queryTicketsParams.getContent());
        wrapper.like(StrUtil.isNotBlank(queryTicketsParams.getName()), TicketsEntity::getName,
                queryTicketsParams.getName());
        wrapper.orderByDesc(TicketsEntity::getCreateTime);
        Page<TicketsEntity> data = ticketsService.page(page, wrapper);
        Page<TicketsVo> voPage = new Page<>();
        BeanUtil.copyProperties(data, voPage, false);
        List<TicketsVo> vos = Lists.newArrayList();
        for (TicketsEntity ticket: data.getRecords()) {
            TicketsVo vo = new TicketsVo();
            BeanUtil.copyProperties(ticket, vo, false);
            vos.add(vo);
        }
        voPage.setRecords(vos);
        return R.ok(voPage);
    }


    @PostMapping(value = "pageTasks")
    @Operation(summary = "查询工单任务")
    public R<Page<TicketsTaskVo>> pageTasks(@RequestBody QueryTasksTicketsParams params) {
        LambdaQueryWrapper<TicketsTaskEntity> wrapper = Wrappers.lambdaQuery();
        Page page = new Page(params.getCurrent(), params.getSize());
        wrapper.eq(TicketsTaskEntity::getTicketsId, params.getTicketsId());
        wrapper.like(TicketsTaskEntity::getContent, params.getContent());
        Page<TicketsTaskEntity> data = ticketsTaskService.page(page, wrapper);
        List<TicketsTaskVo> vos = Lists.newArrayList();
        for (TicketsTaskEntity task : data.getRecords()) {
            TicketsTaskVo vo = new TicketsTaskVo();
            BeanUtil.copyProperties(task, vo, false);
            vos.add(vo);
        }
        Page<TicketsTaskVo> taskVoPage = new Page<>();
        BeanUtil.copyProperties(data, taskVoPage);
        taskVoPage.setRecords(vos);
        return R.ok(taskVoPage);
    }


    @GetMapping(value = "/resume/{ticketsId}")
    @Operation(summary = "恢复工单")
    @PreAuthorize("@pms.hasPermission('tickets_resume')")
    public R resumeTask(@PathVariable Integer ticketsId) {

        TicketsEntity tickets = ticketsService.getById(ticketsId);
        List<TicketsEntity> list = ticketsService.lambdaQuery().gt(TicketsEntity::getId,
                ticketsId).eq(TicketsEntity::getAllotRobotSn,tickets.getAllotRobotSn() )
                .eq(TicketsEntity::getStatus,1).list();
        if(!list.isEmpty()){
            return R.failed("该机器已开始其他工单，不能恢复工单");
        }
        Cache<String, RobotClientSummaryDto> posInfoDtoCache = SpringUtil.getBean("robotCache");

        RobotClientSummaryDto robotClientSummaryDto = posInfoDtoCache.getIfPresent(tickets.getAllotRobotSn());
        Integer emergencyStop = Optional.ofNullable(robotClientSummaryDto).map(RobotClientSummaryDto::getStatus).map(RobotStatusDto::getEmergencyStop).orElse(0);
        if(emergencyStop == 1){
            return R.failed("该机器处于急停状态，不能恢复工单");
        }
        RateLimiter rateLimiter = CustomConstant.ticketsControlLimiterMap.computeIfAbsent(tickets.getAllotRobotSn(), k -> RateLimiter.create(1));
        if (!rateLimiter.tryAcquire(10)){
            return R.failed("任务操作频繁,请稍后重试");
        }
        cmdTickets(tickets, 2);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return R.ok();
    }


    @GetMapping(value = "/pause/{ticketsId}")
    @Operation(summary = "暂停工单")
    @PreAuthorize("@pms.hasPermission('tickets_pause')")
    public R pauseTask(@PathVariable Integer ticketsId) {
        TicketsEntity tickets = ticketsService.getById(ticketsId);
        RateLimiter rateLimiter = CustomConstant.ticketsControlLimiterMap.computeIfAbsent(tickets.getAllotRobotSn(), k -> RateLimiter.create(1));
        if (!rateLimiter.tryAcquire(10)){
            return R.failed("任务操作频繁,请稍后重试");
        }
        cmdTickets(tickets, 1);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return R.ok();
    }


    @GetMapping(value = "/finish/{ticketsId}")
    @Operation(summary = "终止工单")
    @PreAuthorize("@pms.hasPermission('tickets_finish')")
    public R finishTask(@PathVariable Integer ticketsId) {
        TicketsEntity tickets = ticketsService.getById(ticketsId);
        RateLimiter rateLimiter = CustomConstant.ticketsControlLimiterMap.computeIfAbsent(tickets.getAllotRobotSn(), k -> RateLimiter.create(1));
        if (!rateLimiter.tryAcquire(10)){
            return R.failed("任务操作频繁,请稍后重试");
        }
        cmdTickets(tickets, 3);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return R.ok();
    }



    private void cmdTickets(TicketsEntity tickets, Integer cmd) {
        RobotCmdTicketsDto robotCmdTicketsDto = new RobotCmdTicketsDto();
        robotCmdTicketsDto.setClientId(tickets.getAllotRobotSn());
        robotCmdTicketsDto.setCmd(cmd);
        robotCmdTicketsDto.setServerId(tickets.getId());

        RobotSendClientMsgDto robotSendClientMsgDto = new RobotSendClientMsgDto();
        robotSendClientMsgDto.setCmd(ProtocolEnum.ROBOT_CMD_TICKETS.getCmd());
        robotSendClientMsgDto.setClientId(tickets.getAllotRobotSn());
        robotSendClientMsgDto.setData(robotCmdTicketsDto);
        SpringUtil.getApplicationContext().publishEvent(robotSendClientMsgDto);
    }



}
